unit StringRoutines;

interface
	uses
		classes,StrUtils, SysUtils;

	type
    	TSplitArray = array of String;

	Function BooleanToStr(b:boolean):String;
	Function PadRight(Count:Byte; S:String):String;
	Function PadLeft(Count:Byte; S:String):String;
	Function poslast(ch:char; S:string):byte;
	function char2char(ch,ch2:char;S:string):string;
	function DelStr(StrTodel, S:string):string;
	function add_dash_rem_brakets(S:string):string;
	function del_spaces_from_wrong_places(S:string):string;
	function add_spaces_in_right_places(S:string):string;
	Function lowcase(S:string):string;
	Function upcase_first_letters(S:string):string;
	Function toStr(x:integer):string;
	Function Convert_all_but_last_occurance(chFrom,chTo:char; S:string):String;
	Function Convert_all_but_first_occurance(chFrom,chTo:char; S:string):String;
	function SplitX(const Source, Delimiter: String): TSplitArray;
	function Split(Input: string; const Delimiter: Char ):  TStrings;
	function del_double_spaces(s:string):string;
	function del_doubleStr(subS,s:string):string;
   function IsNumeric2(const S: String): Boolean;
   function IsNumeric (const S: String): Boolean;
   function RemoveNumericPrefix(const S: String): String;
   function RemoveLeadingDash(const S: String): String;
   
implementation

Function toStr(x:integer):string;
Var S:string;
Begin
   str(x,s);
   toStr:=s;
End;

Function BooleanToStr(b:boolean):String;
Begin
if b then
   BooleanToStr:='True'
else
   BooleanToStr:='False'
End;

Function PadRight(Count:Byte; S:String):String;
begin
While Length(S)<Count do
     S:=S+' ';
if Length(S)>Count then
   s:=copy(S,0,Count);
PadRight:=s;
end;

Function PadLeft(Count:Byte; S:String):String;
begin
While Length(S)<Count do
     S:=' '+S;
if Length(S)>Count then
   s:=copy(S,0,Count);
PadLeft:=s;
end;

Function poslast(ch:char;S:string):byte;
{returns the last posision of 'ch' found in 's'}
   	var i:integer;
begin
    poslast:=0;
    if s<>'' then
    for i:=1 to length(s) do
    if s[i]=ch then poslast:=i;
end;

Function Convert_all_but_last_occurance(chFrom,chTo:char; S:string):String;
var L:integer;
begin
	Convert_all_but_last_occurance:=s;
	L:=poslast(chFrom,s);
	if l>1 then Convert_all_but_last_occurance:=char2char(chFrom,chTo,LeftStr(s,L-1))+RightStr(s,(Length(s)-L)+1)
end;

Function Convert_all_but_first_occurance(chFrom,chTo:char; S:string):String;
var L:integer;
begin
	Convert_all_but_first_occurance:=s;
	L:=pos(chFrom,s);
	if L>1 then Convert_all_but_first_occurance:=LeftStr(s,L)+char2char(chFrom,chTo,RightStr(s,Length(s)-L ));
end;

function char2char(ch,ch2:char; S:string):string;
var i:integer;
begin
    for i:=1 to length(s) do
    if s[i]=ch then s[i]:=ch2;
    char2char:=s;
end;

function DelStr(StrTodel,S:string):string;
var PosFound:integer;
begin
     Repeat
           PosFound:=pos(StrTodel,s);
           if PosFound>0 then delete(s,PosFound,Length(StrToDel));
     Until PosFound=0;
     DelStr:=s;
end;


function DelStrInRange(StrTodel,S:string; FromX,ToX:integer):string;
//Deletes a string in a Postion Range
var L:integer;
begin
   L:=Length(s);
   //if (L>1) and (L>=FromX) and (L>=ToX) and (FromX>ToX) then
        DelStrInRange:=MidStr(s,0,FromX)+ StringReplace(MidStr(s,FromX,ToX-FromX),StrToDel,'',[rfReplaceAll] )+MidStr(s,ToX+1,L-ToX);
   //else
    //  DelStrInRange:=s;
end;

function add_dash_rem_brakets(s:string):string;
//Removes Brakets before Dash Adds Dash after starting brakets
var i,i1,i2,i3:integer;
begin
	i:=pos('-',s);
	i1:=pos('{',s);
	i2:=pos('}',s);

	if (i<1) and (i2>0) and (i1<2) then //Add dash only if first set of brackets at beginning of string
	begin
		insert('-',s,i2+1);
		i:=pos('-',s);
	end;

	if (i>i2) then s:=DelStrInRange('}',S,0,i-1);
	if (i>i1) then s:=DelStrInRange('{',S,0,i);

	add_dash_rem_brakets:=s;
end;

function del_double_spaces(s:string):string;
begin
   del_double_spaces:=del_doubleStr(' ',s);
end;

function del_doubleStr(subS,s:string):string;
begin
    While pos(SubS+SubS,s)>0 do s:=StringReplace(s,SubS+SubS,SubS,[rfReplaceAll]);
    del_doubleStr:=s;
end;


function del_spaces_from_wrong_places(s:string):string;
var lastdot:integer;
begin
    s:=del_double_spaces(s);

    {del spaces after and before '(',')'}
    if ( (pos('{',s)-1)>0 ) and (s[pos('{',s)-1]=' ') then delete(s,pos('{',s)-1,1);
    if ( (pos('{',s)+1)>0 ) and (s[pos('{',s)+1]=' ') then delete(s,pos('{',s)+1,1);
    if ( (pos('}',s)-1)>0 ) and (s[pos('}',s)-1]=' ') then delete(s,pos('}',s)-1,1);

    {del spaces before last '.'}
    lastdot:=poslast('.',s);
    if (lastdot>0) and (s[lastdot-1]=' ') then delete(s,lastdot-1,1);

    del_spaces_from_wrong_places:=s;
end;

function add_spaces_in_right_places(s:string):string;
var  i,j:integer;
begin
   i:=2;
   j:=length(s);
   if j>2 then
   while i<=j do
   begin
    //Add space after -
    if (s[i]='-') and (s[i+1]<>' ') then
       begin insert(' ',s,i+1); inc(j); end;
    //Add space before -
    if (s[i]='-') and (s[i-1]<>' ') then
       begin insert(' ',s,i); inc(j); end;
    //Add space before {
    if (s[i]='{') and (s[i-1]<>' ') then
       begin insert(' ',s,i); inc(j); end;
    inc(i);
   end;
   add_spaces_in_right_places:=s;
end;

Function lowcase(s:string):string;
    var i:integer;
begin
    if s<>'' then
    for i:=1 to length(s) do
    if (s[i]>='A') and (s[i]<='Z') then s[i]:=chr(ord(s[i])+32);
    lowcase:=s;
end;

Function upcase_first_letters(S:string):string;
    var i:integer;
begin
    if (s[1]>='a') and (s[1]<='z') then s[1]:=upcase(s[1]);
    if length(s)>2 then
    for i:=2 to length(s) do
    if (s[i]>='a') and (s[i]<='z') then
    if (s[i-1]=' ') or (s[i-1]='{') or (s[i-1]='(') or (s[i-1]='.') then s[i]:=upcase(s[i]);
    upcase_first_letters:=s;
end;

function SplitX(const Source, Delimiter: String): TSplitArray;
//Splits a string into pieces using any delimiter
//no classes
var
    iCount,iPos,iLength: Integer;
    sTemp: String;
    aSplit: TSplitArray;
begin
    sTemp   := Source;
    iCount  := 0;
    iLength := Length(Delimiter) - 1;
    repeat
	    iPos := Pos(Delimiter, sTemp);
	    if iPos = 0 then
		    break
	    else begin
		    Inc(iCount);
		    SetLength(aSplit, iCount);
		    aSplit[iCount - 1] := Copy(sTemp, 1, iPos - 1);
		    Delete(sTemp, 1, iPos + iLength);
	    end;
    until False;
    if Length(sTemp) > 0 then begin
	    Inc(iCount);
	    SetLength(aSplit, iCount);
	    aSplit[iCount - 1] := sTemp;
	end;
   Result := aSplit;
end;


function Split (Input: string; const Delimiter: Char): TStrings;
//Splits a  string into pieces using any delimiter
//no classes
Var S:Tstrings;
begin
  S := TStringList.Create;
  Assert(Assigned(S));
  S.Clear;
  S.Delimiter     := Delimiter;
  S.DelimitedText := Input;
  Split:=S;
end;


function IsNumeric(const S: String): Boolean;
begin
  Result:=True;
  Try
    StrToFloat(S);
  Except
    Result:=False;
  end;
end;


function IsNumeric2(const S: String): Boolean;
var
   Numeric : Set of Char;
   iCnt    : Integer;
begin
  Result:=True;
  Numeric:=['0'..'9','.',' ']; // Here you can add other chars
  For iCnt:=1 to Length(S) do
    If Not (S[iCnt] in Numeric) then
      Begin
  	    Result:=False;
    	Exit;
      end;
end;

function RemoveNumericPrefix(const S: String): String;
var
   iCnt    : Integer;
   Numeric : Set of Char;
   chrFound: Boolean;
begin
  iCnt:=0;
  chrFound:=false;
  Numeric:=['0'..'9','.',' ','-']; // Here you can add other chars
  while (icnt<Length(s)) and (icnt<15) and (not chrFound) do
  Begin
   iCnt:=iCnt+1;
   if not (S[iCnt] in Numeric) then chrFound:=True;
  End;
  Result:=RightStr(s,Length(s)-(iCNT-1));
end;

function RemoveLeadingDash(const S: String): String;
var
   iCnt    : Integer;
   Numeric : Set of Char;
   chrFound: Boolean;
begin
  iCnt:=0;
  chrFound:=false;
  Numeric:=['-',' ']; // Here you can add other chars
  while (icnt<Length(s)) and (icnt<6) and (not chrFound) do
  Begin
   iCnt:=iCnt+1;
   if not (S[iCnt] in Numeric) then chrFound:=True;
  End;
  Result:=RightStr(s,Length(s)-(iCNT-1));
end;


end.
